package com.tripreset.sdk.bk

import android.graphics.Bitmap
import android.os.Build
import android.util.JsonReader
import android.util.JsonToken
import android.webkit.*
import com.blankj.utilcode.util.*
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jsoup.Connection
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.StringReader
import java.net.URL


class InJavaScriptLocalObj(private val onHtmlCall: (String) -> Unit) {
    @JavascriptInterface
    fun showSource(html: String) {
        onHtmlCall(html)
    }
}

class CommonDataSource : DataSource {

    private var webView: WebView? = null

    private fun initWebView(callback: ValueCallback<String>) {
        if (webView == null) {
            webView = WebView(Utils.getApp())
            webView?.apply {
                settings.javaScriptEnabled = true
                settings.domStorageEnabled = true
                settings.userAgentString =
                    "Mozilla/5.0 (Linux; Android ${Build.VERSION.RELEASE}; ${Build.MODEL}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Mobile Safari/537.36 $userAgent "
                settings.cacheMode = WebSettings.LOAD_NO_CACHE
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
                }

                webViewClient = object : WebViewClient() {

                    override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                        super.onPageStarted(view, url, favicon)
                        LogUtils.i("===========onPageStarted=========$url")
                    }

                    override fun onPageFinished(view: WebView, url: String?) {
                        super.onPageFinished(view, url)
                        LogUtils.i("============onPageFinished========$url")

                        ThreadUtils.runOnUiThreadDelayed({ evaluateJavascriptHtml(view, callback) }, 1000)

                    }
                }
            }

        }
    }

    private var userAgent: String = "MicroMessenger/6.0.2.56_r958800.520"

    override fun setUserAgent(userAgent: String) {
        this.userAgent = userAgent
    }

    override fun getDataSourceUrl(keyWord: String) = ""

    override suspend fun loadContent(keyWord: String): ContentInfo = loadContent(keyWord, false)

    override suspend fun loadContent(keyWord: String, useWeb: Boolean): ContentInfo {

        return if (useWeb) {
            needLoadJsGetHtml(keyWord)
        } else {
            val document = Jsoup
                .connect(keyWord)
                .userAgent("Mozilla/5.0 (Linux; Android ${Build.VERSION.RELEASE}; ${Build.MODEL}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Mobile Safari/537.36 $userAgent")
                .timeout(60000)
                .method(Connection.Method.GET)
                .followRedirects(true)
                .execute()
                .parse()

            handle(document, keyWord)
        }
    }

    private suspend fun needLoadJsGetHtml(keyWord: String): ContentInfo {
        val deferred = CompletableDeferred<String>()

        withContext(Dispatchers.Main) {
            initWebView {
                deferred.complete(it)
            }
            webView?.loadUrl(keyWord)
        }

        val htmlString = deferred.await()
        return handle(Jsoup.parse(readHtml(htmlString)), keyWord)
    }

    private fun evaluateJavascriptHtml(view: WebView, callback: ValueCallback<String>) {
        val script = "(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();"
        view.evaluateJavascript(script, callback)
    }

    private fun readHtml(html: String): String {
        val reader = JsonReader(StringReader(html))
        reader.isLenient = true
        return try {
            if (reader.peek() == JsonToken.STRING) {
                val domStr = reader.nextString()
                domStr ?: ""
            } else {
                ""
            }
        } catch (e: IOException) {
            ""
        } finally {
            reader.close()
        }
    }

    private suspend fun handle(document: Document, url: String): ContentInfo {
        val title = document.title()
        var introduction = ""

        //val imageList =

        for (element in document.getElementsByTag("meta")) {
            if (element.attr("name") == "description") {
                introduction = element.attr("content")
            }
        }

        //获取 带有src属性的img元素
        //val elements = document.getElementsByTag("img")

        //在父类的目录下创建一个以当前下载的系统时间为文件名的文件//获取src的绝对路径//获取src的绝对路径
        //获取src的绝对路径//获取src的绝对路径
        /* val imageList = elements.take(6).distinct().mapNotNull {


             var src: String = it.attr("data-original") //获取src的绝对路径

             if (src.isEmpty()) {
                 src = it.attr("data-src") //获取src的绝对路径
             }

             if (src.isEmpty()) {
                 src = it.attr("abs:src") //获取src的绝对路径
             }

             val urlString = if (src.isNotEmpty() && !src.contains(".svg") && URLUtil.isNetworkUrl(src)) src else null

             if (urlString.isNullOrEmpty()) {
                 null
             } else {
                 downloadImage(urlString)
             }
         }*/

        return ContentInfo(title, introduction, mutableListOf())
    }

    private fun downloadImage(urlString: String) = try {

        //在父类的目录下创建一个以当前下载的系统时间为文件名的文件
        val download = File(PathUtils.getExternalAppPicturesPath(), EncryptUtils.encryptMD5ToString(urlString))

        if (download.exists()) {
            val size = ImageUtils.getSize(download.absolutePath)
            Image(size[0], size[1], download.absolutePath, urlString)
        } else {
            val url = URL(urlString)
            val openConnection = url.openConnection()
            val inputStream = openConnection.getInputStream()

            val out = FileOutputStream(download)
            val b = ByteArray(2 * 1024)
            var len: Int
            while (inputStream.read(b).also { data -> len = data } != -1) {
                out.write(b, 0, len)
            }
            out.flush()
            out.close()

            val size = ImageUtils.getSize(download.absolutePath)

            val w = size[0]
            val h = size[1]
            //LogUtils.i("============================$w $h")
            if (w >= 150 && h >= 150) {
                Image(size[0], size[1], download.absolutePath, urlString)
            } else {
                FileUtils.delete(download.absolutePath)
                null
            }
        }

    } catch (e: Exception) {
        LogUtils.i(e.localizedMessage)
        null
    }
}